require('dotenv').config();
const SMTPServer = require('smtp-server').SMTPServer;
const express = require('express');
const sqlite3 = require('sqlite3').verbose();
const { engine } = require('express-handlebars');
const path = require('path');
const Buffer = require('buffer').Buffer;
const simpleParser = require('mailparser').simpleParser;
const compression = require('compression');

// 邮件服务相关配置
const smtpConfig = {
  ports: process.env.TEMPEMAIL_SMTP_PORTS.split(',').map(port => parseInt(port.trim())) || [25, 465, 587, 2525],
  defaultPort: parseInt(process.env.TEMPEMAIL_SMTP_DEFAULT_PORT || 465),
  domain: process.env.TEMPEMAIL_SMTP_DOMAIN || 'localhost',
  protocol: process.env.TEMPEMAIL_SMTP_PROTOCOL || 'smtp'
};

// Web服务相关配置
const httpConfig = {
  port: process.env.TEMPEMAIL_HTTP_PORT || 3000,
  domain: process.env.TEMPEMAIL_HTTP_DOMAIN || 'localhost',
  protocol: process.env.TEMPEMAIL_HTTP_PROTOCOL || 'http'
};

// 生成完整的Web服务URL
const baseUrl = `${httpConfig.protocol}://${httpConfig.domain}:${httpConfig.port}`;

// 创建数据库连接
const db = new sqlite3.Database('emails.db', (err) => {
  if (err) {
    console.error('创建数据库连接失败:', err);
    process.exit(1); // 如果无法创建数据库连接，则退出程序
  }
  console.log('数据库连接已建立');
  
  // 初始化数据库表
  db.serialize(() => {
    // 使用 serialize 确保所有操作按顺序执行
    db.run(`
      CREATE TABLE IF NOT EXISTS emails (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        to_address TEXT,
        from_address TEXT,
        content TEXT,
        received_at DATETIME
      )
    `, (err) => {
      if (err) {
        console.error('创建数据表失败:', err);
        process.exit(1);
      }
      console.log('数据表初始化成功');
      
      // 创建索引
      db.run(`
        CREATE INDEX IF NOT EXISTS idx_emails_to_address ON emails(to_address);
        CREATE INDEX IF NOT EXISTS idx_emails_received_at ON emails(received_at);
      `, (err) => {
        if (err) {
          console.error('创建索引失败:', err);
          // 索引创建失败不需要退出程序
        } else {
          console.log('索引创建成功');
        }
      });
    });
  });
});

// 设置错误处理
db.on('error', (err) => {
  console.error('数据库错误:', err);
});

process.on('exit', () => {
  // 确保程序退出时关闭数据库连接
  db.close((err) => {
    if (err) {
      console.error('关闭数据库连接失败:', err);
    }
  });
});

// 清理过期邮件的函数
function cleanupExpiredEmails() {
  const sevenDaysAgo = new Date();
  sevenDaysAgo.setDate(sevenDaysAgo.getDate() - 7);
  
  db.run(
    'DELETE FROM emails WHERE received_at < ?',
    [sevenDaysAgo.toISOString()],
    function(err) {
      if (err) {
        console.error('清理过期邮件失败:', err);
      } else if (this.changes > 0) {
        console.log(`已清理 ${this.changes} 封过期邮件`);
      }
    }
  );
}

// 每天执行一次清理
setInterval(cleanupExpiredEmails, 24 * 60 * 60 * 1000);
// 启动时也执行一次清理
cleanupExpiredEmails();

// 处理邮件内容，移除附件
async function processEmailContent(content) {
  try {
    const parsed = await simpleParser(content, {
      skipHtmlToText: true,
      skipTextLinks: true,
      maxHtmlLengthToParse: 1024 * 1024, // 1MB
      timeout: 5000
    });
    
    // 创建一个对象来存储所有可用的内容格式
    const processedEmail = {
      subject: parsed.subject,
      from: parsed.from.text,
      to: parsed.to.text,
      date: parsed.date,
      attachments: parsed.attachments.map(({filename, contentType, size}) => ({
        filename, contentType, size
      }))
    };

    // 只包含有内容的字段
    if (parsed.text) {
      processedEmail.text = parsed.text;
    }
    if (parsed.html) {
      processedEmail.html = parsed.html;
    }
    if (content) {
      processedEmail.raw = content.toString();
    }

    return JSON.stringify(processedEmail);
  } catch (error) {
    console.error('处理邮件内容时出错:', error);
    return content.toString();
  }
}

// 设置 SMTP 服务器
smtpConfig.ports.forEach(port => {
  const smtpServerInstance = new SMTPServer({
    allowInsecureAuth: true,
    authOptional: true,
    host: '0.0.0.0',
    disabledCommands: ['STARTTLS'],
    onConnect(session, callback) {
      console.log(`SMTP 连接建立 (端口 ${port}):`, session.remoteAddress);
      callback();
    },
    onRcptTo(address, session, callback) {
      const domain = address.address.split('@')[1];
      // 检查收件地址是否使用允许的域名
      if (domain.toLowerCase() !== smtpConfig.domain.toLowerCase() && 
          domain.toLowerCase() !== httpConfig.domain.toLowerCase()) {
        return callback(new Error(`Invalid recipient domain. Please use ${smtpConfig.domain} or ${httpConfig.domain}`));
      }
      callback();
    },
    onData(stream, session, callback) {
      // 使用 Buffer 来收集数据
      const chunks = [];
      
      stream.on('data', (chunk) => {
        chunks.push(chunk);
      });
      
      stream.on('end', async () => {
        // 将所有 chunks 合并成一个 Buffer
        const mailContent = Buffer.concat(chunks);
        const toAddress = session.envelope.rcptTo[0].address;
        const fromAddress = session.envelope.mailFrom.address;
        const currentTime = new Date().toISOString(); // 使用 JS 获取当前时间
        
        try {
          // 处理邮件内容
          const processedContent = await processEmailContent(mailContent);
          
          // 打印邮件内容到控制台
          console.log('\n收到新邮件 ================');
          console.log('发件人:', fromAddress);
          console.log('收件人:', toAddress); 
          console.log('接收时间:', currentTime);
          console.log('邮件内容已处理');
          console.log('==========================\n');

          // 保存到数据库，使用参数化的时间戳
          db.run(
            `INSERT OR REPLACE INTO emails (to_address, from_address, content, received_at) 
             VALUES (?, ?, ?, ?)`,
            [toAddress, fromAddress, processedContent, currentTime],
            function(err) {
              if (err) {
                console.error('保存邮件失败:', err);
                callback(err);
              } else {
                console.log('邮件已更新, ID:', this.lastID);
                callback();
              }
            }
          );
        } catch (error) {
          console.error('处理邮件失败:', error);
          callback(error);
        }
      });
    }
  });

  smtpServerInstance.listen(port, '0.0.0.0', () => {
    console.log(`SMTP 服务器运行在 0.0.0.0:${port}`);
    if (port === smtpConfig.defaultPort) {
      console.log(`默认 SMTP 端口: ${port}`);
    }
  }).on('error', err => {
    console.error(`SMTP 服务器错误 (端口 ${port}):`, err);
  });
});

// 设置 Express 应用
const app = express();
app.engine('handlebars', engine());
app.set('view engine', 'handlebars');
app.set('views', path.join(__dirname, 'views'));

// 启用 gzip 压缩
app.use(compression());

// 设置静态资源缓存
app.use(express.static(path.join(__dirname, 'public'), {
    maxAge: '1h',
    etag: true
}));

// 设置请求超时
app.use((req, res, next) => {
    res.setTimeout(5000, () => {
        res.status(408).json({ error: '请求超时' });
    });
    next();
});

// 路由理
app.get('/', (req, res) => {
  res.render('home', {
    domain: smtpConfig.domain,
    debug: isDebug  // 传递 debug 状态到模板
  });
});

app.get('/check/:email', async (req, res) => {
    try {
        const email = req.params.email;
        const since = req.query.since ? parseInt(req.query.since) : null;
        
        console.log('检查邮件请求:', {
            email,
            since,
            sinceDate: since ? new Date(since).toISOString() : null
        });

        // 修改查询语句，使用参数化的时间比较
        const query = `
            SELECT * FROM emails 
            WHERE to_address = ? 
            AND strftime('%s', received_at) * 1000 > ?
            ORDER BY received_at DESC 
            LIMIT 1
        `;
        
        db.get(query, [email, since || 0], (err, row) => {
            if (err) {
                console.error('数据库查询失败:', err);
                res.status(500).json({ error: '查询失败' });
                return;
            }
            
            if (row) {
                // 有新邮件，返回内容和邮件的接收时间
                res.json({
                    content: row.content,
                    timestamp: new Date(row.received_at).getTime()
                });
            } else {
                // 没有新邮件，返回上次查询的时间戳
                res.json({
                    content: null,
                    timestamp: since || Date.now()
                });
            }
        });
    } catch (error) {
        console.error('检查邮件失败:', error);
        res.status(500).json({ error: '检查邮件失败' });
    }
});

// 在文件开头添加调试模式检查
const isDebug = process.argv.includes('--debug');

// 修改 /all-emails 路由，使其只在调试模式下可用
if (isDebug) {
    app.get('/all-emails', (req, res) => {
        console.log('调试模式: 请求所有邮件');
        db.all('SELECT * FROM emails ORDER BY received_at DESC', (err, rows) => {
            if (err) {
                console.error('查询失败:', err);
                res.status(500).json({ error: err.message });
            } else {
                // 处理每个邮件的内容
                const processedRows = rows.map(row => {
                    try {
                        return {
                            ...row,
                            content: JSON.parse(row.content)
                        };
                    } catch (e) {
                        return row;
                    }
                });
                res.json({
                    total: rows.length,
                    emails: processedRows
                });
            }
        });
    });

    // 添加一个简单的调试信息路由
    app.get('/debug-info', (req, res) => {
        res.json({
            mode: 'debug',
            startTime: new Date().toISOString(),
            endpoints: [
                '/all-emails - 获取所有邮件',
                '/debug-info - 获取调试信息'
            ]
        });
    });

    console.log('调试模式已启用');
    console.log('可用的调试端点:');
    console.log('- GET /all-emails : 获取所有存储的邮件');
    console.log('- GET /debug-info : 获取调试信息');
}

// 修改测试邮件路由
app.post('/send-test-email', (req, res) => {
    const { exec } = require('child_process');
    // 从请求体中获取当前选择的邮箱地址
    const targetEmail = req.query.email;
    
    if (!targetEmail) {
        return res.status(400).json({ error: '未指定目标邮箱' });
    }

    exec(`node test-smtp.js "${targetEmail}"`, (error, stdout, stderr) => {
        if (error) {
            console.error(`执行错误: ${error}`);
            return res.status(500).json({ error: '发送失败' });
        }
        console.log(`输出: ${stdout}`);
        res.json({ message: '测试邮件已发送' });
    });
});

app.listen(httpConfig.port, () => {
  console.log(`Web 服务器运行在端口 ${httpConfig.port}`);
  console.log(`Web 协议: ${httpConfig.protocol}`);
  console.log(`邮件域名: ${smtpConfig.domain}`);
  console.log(`邮件协议: ${smtpConfig.protocol}`);
  console.log(`支持的 SMTP 端口: ${smtpConfig.ports.join(', ')}`);
  console.log(`请访问 ${httpConfig.protocol}://${httpConfig.domain}:${httpConfig.port} 查看邮箱界面`);
}); 